#ifndef _SCIENCE_MATHEMATICS_ALGEBRA_INTERVAL_H_
#define _SCIENCE_MATHEMATICS_ALGEBRA_INTERVAL_H_
//-----------------------------------------------------------------------------------------------------//
//																	                                   //
// interval.h  contains definitions of the interval notations and the                                  //
// functions needed to operate the interval usage.					                                   //
// it supports all types of intervals (closed, opened, and infinite)                                   //
//																									   //
// author	: Eng. Ahmed Yasser																		   //
// data		: 20-01-2015																			   //
//																	                                   //
//-----------------------------------------------------------------------------------------------------//

#include <vector>
#include <stdio.h>
#include <string.h>
#include <limits>	
#include <sstream>
#include <string>

//-----------------------------------------------------------------------------------------------------//
//																	   								   //
// the types of the interval										   								   //
//																									   //
//-----------------------------------------------------------------------------------------------------//
#define CLOSED_INTERVAL		0x00000001	// closed interval
#define OPENED_INTERVAL		0x00000002  // opened interval
#define INFINITE_INTERVAL	0x00000003	// infinite interval which is closed too

//-----------------------------------------------------------------------------------------------------//
//																									   //
// the infinite numbers																				   //
//																									   //
//-----------------------------------------------------------------------------------------------------//
#define POSITIVE_INFINITE FLT_MAX
#define NEGATIVE_INFINITE -FLT_MAX

//-----------------------------------------------------------------------------------------------------//
//																									   //
// the structure that define the interval															   //
//																									   //
//-----------------------------------------------------------------------------------------------------//
struct interval_t
{
	float start;				// the start of the interval
	float end;					// the end of the interval
	unsigned int start_type;	// the type of the start interval 
	unsigned int end_type;		// the type of the end interval
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_interval																		   //
//																									   //
// desc		: create an interval between the start and end with the type specified					   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//		int start_type	: type of the starting interval (opened, closed, ...)						   //
//		float end		: the end of the interval													   //
//		int end_type	: type of the ending interval (opened, closed, ...)							   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_interval(float start, int start_type, float end, int end_type);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_closed_closed_interval															   //
//																									   //
// desc		: create full closed interval in the form [a, b]										   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_closed_closed_interval(float start, float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_closed_opened_interval															   //
//																									   //
// desc		: create interval in the form [a, b)													   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_closed_opened_interval(float start, float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_opened_closed_interval															   //
//																									   //
// desc		: create interval in the form (a, b]													   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_opened_closed_interval(float start, float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_opened_opened_interval															   //
//																									   //
// desc		: create interval in the form (a, b)													   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_opened_opened_interval(float start, float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_closed_infinite_interval														   //
//																									   //
// desc		: create interval in the form [a, POSITIVE_INFINITE)									   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_closed_infinite_interval(float start);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_opened_infinite_interval														   //
//																									   //
// desc		: create interval in the form (a, POSITIVE_INFINITE)									   //
//																									   //
// params	:																						   //
//		float start	: the start of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_opened_infinite_interval(float start);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_negative_infinite_closed_interval												   //
//																									   //
// desc		: create interval in the form (NEGATIVE_INFINITE, b]									   //
//																									   //
// params	:																						   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_negative_infinite_closed_interval(float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_negative_infinite_opened_interval														   //
//																									   //
// desc		: create interval in the form (NEGATIVE_INFINITE, b)									   //
//																									   //
// params	:																						   //
//		float end		: the end of the interval													   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_negative_infinite_opened_interval(float end);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: create_infinite_infinite_interval														   //
//																									   //
// desc		: create interval in the form (NEGATIVE_INFINITE, POSITIVE_INFINITE)					   //
//																									   //
// returns	: the created interval																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
interval_t create_infinite_infinite_interval();

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: evaluate_interval																		   //
//																									   //
// desc		: evaluates the interval on the step attached											   //
//																									   //
// params	:																						   //
//		const interval_t& interval		: the interval to be evaluated								   //
//      float step : the step used in evaluating the interval										   //
// returns	: the converted string																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<float> evaluate_interval(const interval_t& interval, float step);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// name		: print_interval																		   //
//																									   //
// desc		: output the interval to the string format												   //
//																									   //
// params	:																						   //
//		const interval_t& interval		: the interval to be printed								   //
// returns	: the converted string																	   //
/////////////////////////////////////////////////////////////////////////////////////////////////////////
std::string print_interval(const interval_t& interval);

#endif